package me.luger.project.fof.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import me.luger.core.commom.util.*;
import me.luger.core.dao.nutz.service.BaseService;
import me.luger.project.fof.entity.*;
import me.luger.project.fof.entity.ext.TaskParams;
import me.luger.project.fof.entity.ext.TaskParams.UpDownParamsBean;
import me.luger.project.fof.entity.ext.TaskParams.BenchmarkParamsBean;
import org.apache.commons.collections.map.HashedMap;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.File;
import java.io.IOException;
import java.util.*;

@Repository
public class FofTaskService extends BaseService<FofTask> {

    public static final String ASSET_STRATEGY_RESULT_PATH = "/data/fof/matlabFile/AssetAlloc_v2/";

    @Autowired
    private FundNavService fundNavService;

    @Autowired
    private BenchmarkService benchmarkService;

    @Autowired
    private BenchmarkPriceService benchmarkPriceService;

    @Autowired
    private AssetStrategyInfoService assetStrategyInfoService;

    public FofTaskService(Dao dao) {
        super(dao);
    }

    public FofTask addTask(int calType, String params,String bizId) {
        String taskId = LogUtil.getLogId();
        FofTask fofTask = new FofTask();

        fofTask.setTaskId(taskId);
        fofTask.setStartTime(new Date());
        fofTask.setUpdateTime(new Date());
        fofTask.setType(calType);
        fofTask.setStatus(FofTask.TASK_STATUS.INIT.status());
        fofTask.setParams(params);
        fofTask.setBizId(bizId);
        fofTask = insert(fofTask);
        return fofTask;
    }

    public FofTask getTaskByTaskId(String taskId) {
        FofTask fofTask = this.fetchOne(Cnd.NEW().and("taskId", "=", taskId));
        return fofTask;
    }

    public FofTask getTaskByBizIdAndType(String bizId,int type){
        FofTask fofTask = this.fetchOne(Cnd.NEW().and("bizId","=",bizId).and("type","=",type));
        return fofTask;
    }

    public FofTask getToDoTask() {
        FofTask fofTask = this.fetchOne(Cnd.NEW().and("status", "=", "1").orderBy("startTime", "desc"));
        return fofTask;
    }

    public void startTask(String taskId) {
        FofTask task = this.getTaskByTaskId(taskId);

        if (null == task) {
            return;
        }
        int taskType = task.getType();
        LogUtil.debugLog("taskType=" + taskType);
        try {
            if (taskType == 1) {//资产/策略配置任务计算开始
                task = startAssetStrategyConfigTask(task);
            }else if (taskType == 2) {//组合优化任务计算开始
                task = startCombinatorialTask(task);
            }
        } catch (Exception e) {
            task.setStatus(FofTask.TASK_STATUS.FAIL.status());
            task.setMsg(e.getMessage());
            LogUtil.errorLog(e, "模型计算错误 taskId = " + taskId);
        }
        update(task);
    }


    /**
     * 资产/策略配置任务计算开始
     *
     * @return
     */
    private FofTask startAssetStrategyConfigTask(FofTask task) {
        String paramStr = task.getParams();
        TaskParams taskParams = JsonUtil.parse(paramStr, TaskParams.class);
        List<BenchmarkParamsBean> benchmarkParamsBeanList = taskParams.getBenchmarkParams();

        String dirPath = ASSET_STRATEGY_RESULT_PATH + DateUtil.formatNow(DateUtil.DATE_YYYYMMDD);

        String modelId = taskParams.getModelId();
        String modelMatlabFileName = "", backYear = "";
        if ("1".equals(modelId)) {
            modelMatlabFileName = "EffFrontier_cont";
            backYear = taskParams.getModelParams().get(1).getValue();
            genEffFrontierParaFile(dirPath, task.getTaskId(), taskParams,null);
        } else if ("2".equals(modelId)) {
            modelMatlabFileName = "Black_Litterman";
            backYear = taskParams.getModelParams().get(0).getValue();
            genBlackLittermanParaFile(dirPath,task.getTaskId(),taskParams,null);
        } else if ("3".equals(modelId)) {
            removeCurrency(taskParams);
            modelMatlabFileName = "Risk_Parity";
            backYear = taskParams.getModelParams().get(0).getValue();
            genRiskParityParaFile(dirPath, task.getTaskId(), taskParams,null);
        } else if ("4".equals(modelId)) {
            task.setStatus(FofTask.TASK_STATUS.SUCESS.status());
            return task;
        }


        Calendar startCal = DateUtil.nowAsCalendar();
        Date startDate = null;
        Date endDate = DateUtil.nowAsDate();
        if ("1".equals(backYear)) {
            startCal.add(Calendar.YEAR, -1);
        } else if ("2".equals(backYear)) {
            startCal.add(Calendar.YEAR, -3);
        } else if ("3".equals(backYear)) {
            startCal.add(Calendar.YEAR, -5);
        }
        startDate = startCal.getTime();

        List<Map> allFundNavList = new ArrayList<Map>();
        for (BenchmarkParamsBean param : benchmarkParamsBeanList) {
            Integer id = param.getId();
            Benchmark benchmark = benchmarkService.fetchById(id);
            String windCode = benchmark.getWindCode();

            Map<String, Double> datePriceMap = benchmarkPriceService.getFullBenchMarkPriceList(windCode, startDate, endDate);
            if (null == datePriceMap) continue;
            allFundNavList.add(datePriceMap);
        }

        StringBuilder sb = new StringBuilder();
        while (startDate.before(endDate)) {
            sb.append(DateUtil.format(startDate, "dd/MM/yyyy") + "\t");
            for (Map<String, Double> datePriceMap : allFundNavList) {
                String curDateFmt = DateUtil.format(startDate, DateUtil.DATE_YYYY_MM_DD);
                sb.append(datePriceMap.get(curDateFmt) + "\t");
            }
            startDate = DateUtil.add(startDate, 24 * 60 * 60);
            sb.append("\n");
        }


        String matlabExePath = dirPath + File.separator + task.getTaskId();
        try {
            File dirFile = new File(dirPath);
            FileUtil.forceMkdir(dirFile);

            File dataFile = new File(dirFile, task.getTaskId() + "_Data.txt");
            FileUtil.write(dataFile, sb.toString());
        } catch (IOException e) {
            task.setStatus(FofTask.TASK_STATUS.FAIL.status());
            task.setMsg("创建DATA文件失败");
            LogUtil.errorLog(e.getMessage());
            return task;
        }


        String matlabExeShellCmd = "cd /data/fof/matlabFile/AssetAlloc_v2/;/usr/local/MATLAB/R2015b/bin/matlab -nodesktop -nosplash -nodisplay -r \"%s('%s')\"";

        try {
            matlabExeShellCmd = String.format(matlabExeShellCmd, modelMatlabFileName, matlabExePath);
            LogUtil.debugLog(" matlab matlabExeShellCmd=" + matlabExeShellCmd);
            CommandResult commandResult = ShellUtil.execCommand(matlabExeShellCmd);
            LogUtil.debugLog("matlab commandResult=" + commandResult.toString());
            task.setStatus(FofTask.TASK_STATUS.SUCESS.status());
            LogUtil.debugLog("matlab execute status =" + FofTask.TASK_STATUS.SUCESS.status());
            task.setDataDir(dirPath);
        } catch (Exception e) {
            LogUtil.errorLog(e, "execute matlab error");
            task.setStatus(FofTask.TASK_STATUS.FAIL.status());
            task.setMsg("execute matlab error");
            return task;
        }
        return task;
    }

    private void removeCurrency(TaskParams taskParams) {
        List<BenchmarkParamsBean> benchmarkParamsBeanList = taskParams.getBenchmarkParams();
        List<UpDownParamsBean> upDownParamsBeanList = taskParams.getUpDownParams();

        int index = 0;
        for(int i = 0;i<upDownParamsBeanList.size();i++){
            UpDownParamsBean upDownParamsBean = upDownParamsBeanList.get(i);
            if(upDownParamsBean.getAssetStrategyId() == 7){
                index = i;
                break;
            }
        }

        upDownParamsBeanList.remove(index);
        benchmarkParamsBeanList.remove(index);
    }

    /**
     * 组合优化任务开始
     *
     * @param combinatorialTask
     * @return
     */
    private FofTask startCombinatorialTask(FofTask combinatorialTask) throws Exception {
        String bizId = combinatorialTask.getBizId();
        FofTask assetStrategyTask = this.getTaskByBizIdAndType(bizId,1);
        if(null == assetStrategyTask){
            throw new Exception(StringUtil.format("未找到bizId为{0}的前置任务",bizId));
        }
        String combinatorialParamStr = combinatorialTask.getParams();
        String assetStrategyResult = assetStrategyTask.getAssetStrategyResult();
        TaskParams combinatorialTaskParams = JsonUtil.parse(combinatorialParamStr, TaskParams.class);
        Map<Integer,Double> assetStrategyMap = parseAssetStrategyResult(assetStrategyResult);
        List<UpDownParamsBean> upDownParamsBeanList = combinatorialTaskParams.getUpDownParams();

        String dirPath = ASSET_STRATEGY_RESULT_PATH + DateUtil.formatNow(DateUtil.DATE_YYYYMMDD);

        String modelId = combinatorialTaskParams.getModelId();
        String modelMatlabFileName = "", backYear = "1";
        if ("1".equals(modelId)) {
            modelMatlabFileName = "EffFrontier_cont";
            backYear = combinatorialTaskParams.getModelParams().get(1).getValue();
            genEffFrontierParaFile(dirPath, combinatorialTask.getTaskId(), combinatorialTaskParams,assetStrategyMap);
        } else if ("2".equals(modelId)) {
            modelMatlabFileName = "Black_Litterman";
            backYear = combinatorialTaskParams.getModelParams().get(0).getValue();
            genBlackLittermanParaFile(dirPath,combinatorialTask.getTaskId(),combinatorialTaskParams,assetStrategyMap);
        } else if ("3".equals(modelId)) {
            modelMatlabFileName = "Risk_Parity";
            backYear = combinatorialTaskParams.getModelParams().get(0).getValue();
            genRiskParityParaFile(dirPath, combinatorialTask.getTaskId(), combinatorialTaskParams,assetStrategyMap);
        } else if ("4".equals(modelId)) {
            modelMatlabFileName = "EffFrontier_cont";
            genEffFrontierParaFile(dirPath, combinatorialTask.getTaskId(), combinatorialTaskParams,null);
        }

        Calendar startCal = DateUtil.nowAsCalendar();
        Date startDate = null;
        Date endDate = DateUtil.nowAsDate();
        if ("1".equals(backYear)) {
            startCal.add(Calendar.YEAR, -1);
        } else if ("2".equals(backYear)) {
            startCal.add(Calendar.YEAR, -3);
        } else if ("3".equals(backYear)) {
            startCal.add(Calendar.YEAR, -5);
        }
        startDate = startCal.getTime();

        List<Map> allFundNavList = new ArrayList<Map>();
        for (UpDownParamsBean param : upDownParamsBeanList) {
            String extCode = param.getId();
            List<FundNav> fundNavList = fundNavService.getFundNavTrendByDateRange(extCode, startDate, endDate);
            fundNavList = fundNavService.fullFundNavList(fundNavList, startDate, endDate);
            Map<String, Double> datePriceMap = new HashedMap();
            for (FundNav fundNav : fundNavList) {
                datePriceMap.put(DateUtil.format(fundNav.getStatisticDate(), DateUtil.DATE_YYYY_MM_DD), fundNav.getSwanav());
            }
            if (null == datePriceMap) continue;
            allFundNavList.add(datePriceMap);
        }

        StringBuilder sb = new StringBuilder();
        while (startDate.before(endDate)) {
            sb.append(DateUtil.format(startDate, "dd/MM/yyyy") + "\t");
            for (Map<String, Double> datePriceMap : allFundNavList) {
                String curDateFmt = DateUtil.format(startDate, DateUtil.DATE_YYYY_MM_DD);
                sb.append(datePriceMap.get(curDateFmt) + "\t");
            }
            startDate = DateUtil.add(startDate, 24 * 60 * 60);
            sb.append("\n");
        }


        String matlabExePath = dirPath + File.separator + combinatorialTask.getTaskId();
        try {
            File dirFile = new File(dirPath);
            FileUtil.forceMkdir(dirFile);

            File dataFile = new File(dirFile, combinatorialTask.getTaskId() + "_Data.txt");
            FileUtil.write(dataFile, sb.toString());
        } catch (IOException e) {
            LogUtil.errorLog(e.getMessage());
            combinatorialTask.setStatus(FofTask.TASK_STATUS.FAIL.status());
            combinatorialTask.setMsg("创建Data文件失败");
            return combinatorialTask;
        }


        String matlabExeShellCmd = "cd /data/fof/matlabFile/AssetAlloc_v2/;/usr/local/MATLAB/R2015b/bin/matlab -nodesktop -nosplash -nodisplay -r \"%s('%s')\"";

        try {
            matlabExeShellCmd = String.format(matlabExeShellCmd, modelMatlabFileName, matlabExePath);
            LogUtil.debugLog(" matlab matlabExeShellCmd=" + matlabExeShellCmd);
            CommandResult commandResult = ShellUtil.execCommand(matlabExeShellCmd);
            LogUtil.debugLog("matlab commandResult=" + commandResult.toString());
            combinatorialTask.setStatus(FofTask.TASK_STATUS.SUCESS.status());
            LogUtil.debugLog("matlab execute status =" + FofTask.TASK_STATUS.SUCESS.status());
            combinatorialTask.setDataDir(dirPath);
        } catch (Exception e) {
            LogUtil.errorLog(e, "execute matlab error");
            combinatorialTask.setStatus(FofTask.TASK_STATUS.FAIL.status());
            combinatorialTask.setMsg("execute matlab error");
            return combinatorialTask;
        }

        update(combinatorialTask);
        return combinatorialTask;
    }


    /**
     * 刘璐你好，我更新了一下风险平价模型。附件中是程序，以及数据和配置文件。这个例子是指一个五类资产或者五个基金的情况。
     * 这次同样的替换matlab代码，但是参数会多出一行：
     * 第一行，（1，1）表示现金杠杆的成本，默认是3%，（1，2）表示最高的杠杆比率，默认是3倍；
     * 第二行，（2，1）表示在风险平价前沿上的样本数量；
     * 第三、四行表示各类资产的下限和上限，对应原来的第二、三行；
     * 第五行表示组别号码，对应原来的第四行；
     * 第六、七行表示组别的上下限，对应原来的第五、六行。
     * <p>
     * 0.03    3    0    0    0
     * 100    0    0    0    0
     * 0    0    0    0    0
     * 1    1    1    1    1
     * 1    1    2    2    3
     * 0.50    0.30    0.20    0    0
     * 0.50    0.30    0.20    0    0
     * <p>
     * <p>
     * 这次的输出文件：*_COV跟以前是一样的，
     * 而对于*_Output跟之前的区别是：假设有N类资产/基金作为输入，
     * 第一列是新增的现金的比例，而第2列到第N+1列代表N类资产的比例，而N+2代表收益，N+3列代表风险。（最后两列跟原来一样。输出文件跟之前的输出文件的主要区别就是多插入了一列，第一列现金的比例。）
     *
     * @param dirPath
     * @param taskId
     * @param combinatorialTaskParams
     */
    private void genRiskParityParaFile(String dirPath, String taskId, TaskParams combinatorialTaskParams,Map<Integer,Double> assetStrategyMap) {
        List<String> paramLine1List = new ArrayList<String>();
        List<String> paramLine2List = new ArrayList<String>();
        List<String> paramLine3List = new ArrayList<String>();
        List<String> paramLine4List = new ArrayList<String>();
        List<String> paramLine5List = new ArrayList<String>();
        List<String> paramLine6List = new ArrayList<String>();
        List<String> paramLine7List = new ArrayList<String>();

        int calType = combinatorialTaskParams.getCalType();

        //第一行，（1，1）表示现金杠杆的成本，默认是3%，（1，2）表示最高的杠杆比率，默认是3倍；
        paramLine1List.add("0.03");
        paramLine1List.add("15");

        //第二行，（2，1）表示在风险平价前沿上的样本数量；
        paramLine2List.add("100");

        //第三、四行表示各类资产的下限和上限，对应原来的第二、三行；
        List<UpDownParamsBean> combinatorialUpDownParamsBeanList = combinatorialTaskParams.getUpDownParams();
        int assetStrategyLen = combinatorialUpDownParamsBeanList.size();

        for (int i = 0; i < combinatorialUpDownParamsBeanList.size(); i++) {
            UpDownParamsBean upDownParamsBean = combinatorialUpDownParamsBeanList.get(i);
            String assetName = upDownParamsBean.getName();
            if(assetName.contains("货币")){
                continue;
            }
            paramLine3List.add(Long.valueOf(upDownParamsBean.getDown()) / 100D + "");
            paramLine4List.add(Long.valueOf(upDownParamsBean.getUp()) / 100D + "");
            paramLine5List.add(upDownParamsBean.getAssetStrategyId() + "");
            if(null == assetStrategyMap){
                paramLine6List.add(Long.valueOf(upDownParamsBean.getDown()) / 100D + "");
                paramLine7List.add(Long.valueOf(upDownParamsBean.getUp()) / 100D + "");
            }else{
                paramLine6List.add(assetStrategyMap.get(upDownParamsBean.getAssetStrategyId()) + "");
                paramLine7List.add(assetStrategyMap.get(upDownParamsBean.getAssetStrategyId()) + "");
            }

        }

        File dirFile = new File(dirPath);
        try {
            FileUtil.forceMkdir(dirFile);
        } catch (IOException e) {
            LogUtil.errorLog(e,"");
        }

        File paramFile = new File(dirFile, taskId + "_Para.txt");

        write2ParamFile(paramFile,paramLine1List,paramLine2List,paramLine3List,paramLine4List,paramLine5List,paramLine6List,paramLine7List);

    }


    public boolean genEffFrontierParaFile(String dirPath, String taskId, TaskParams combinatorialTaskParams,Map<Integer,Double> assetStrategyMap) {
        List<String> paramLine1List = new ArrayList<String>();
        List<String> paramLine2List = new ArrayList<String>();
        List<String> paramLine3List = new ArrayList<String>();
        List<String> paramLine4List = new ArrayList<String>();
        List<String> paramLine5List = new ArrayList<String>();
        List<String> paramLine6List = new ArrayList<String>();

        List<TaskParams.ModelParamsBean> modelParams = combinatorialTaskParams.getModelParams();


        List<UpDownParamsBean> combinatorialUpDownParamsBeanList = combinatorialTaskParams.getUpDownParams();
        int assetStrategyLen = combinatorialUpDownParamsBeanList.size();


        String dotCountParam = "1000",traceLengthParam = "3";
        if(null != modelParams && modelParams.size() ==2 && null != modelParams.get(0)){
            dotCountParam = modelParams.get(0).getValue();
        }
        if(null != modelParams && modelParams.size() ==2 && null != combinatorialTaskParams.getModelParams().get(1)){
            traceLengthParam = combinatorialTaskParams.getModelParams().get(1).getValue();
        }

        int traceLength = 3, dotCountOnchart = 100;
        if ("1".equals(dotCountParam)) {
            dotCountOnchart = 100;
        } else if ("2".equals(dotCountParam)) {
            dotCountOnchart = 1000;
        } else if ("3".equals(dotCountParam)) {
            dotCountOnchart = 3000;
        }

        if ("1".equals(traceLengthParam)) {
            traceLength = 1 * 250;
        } else if ("2".equals(traceLengthParam)) {
            traceLength = 3 * 250;
        } else if ("3".equals(traceLengthParam)) {
            traceLength = 5 * 250;
        }

        paramLine1List.add(dotCountOnchart + "");
        paramLine1List.add(traceLength + "");

        Map<Integer,Integer> assetStrategyIdGroupIdMap = new LinkedHashMap();
        int groupId = 1;
        for (int i = 0; i < combinatorialUpDownParamsBeanList.size(); i++) {
            UpDownParamsBean upDownParamsBean = combinatorialUpDownParamsBeanList.get(i);
            paramLine2List.add(Long.valueOf(upDownParamsBean.getDown()) / 100D + "");
            paramLine3List.add(Long.valueOf(upDownParamsBean.getUp()) / 100D + "");
            if(assetStrategyIdGroupIdMap.containsKey(upDownParamsBean.getAssetStrategyId())){
                paramLine4List.add(assetStrategyIdGroupIdMap.get(upDownParamsBean.getAssetStrategyId()) + "");
            }else{
                paramLine4List.add(groupId + "");
                assetStrategyIdGroupIdMap.put(upDownParamsBean.getAssetStrategyId(),groupId);
                groupId++;
            }
//            paramLine4List.add(upDownParamsBean.getAssetStrategyId() + "");
            if(null == assetStrategyMap){
                paramLine5List.add(Long.valueOf(upDownParamsBean.getDown()) / 100D + "");
                paramLine6List.add(Long.valueOf(upDownParamsBean.getUp()) / 100D + "");
            }
        }

        if(null != assetStrategyMap){
            for(Map.Entry<Integer,Integer> entry : assetStrategyIdGroupIdMap.entrySet()){
                Integer assetStrategyId = entry.getKey();
                paramLine5List.add(assetStrategyMap.get(assetStrategyId) + "");
                paramLine6List.add(assetStrategyMap.get(assetStrategyId) + "");
            }
        }

        int maxLenth = paramLine1List.size();
        if (paramLine2List.size() > maxLenth) {
            maxLenth = paramLine2List.size();
        }
        if (paramLine3List.size() > maxLenth) {
            maxLenth = paramLine3List.size();
        }
        if (paramLine4List.size() > maxLenth) {
            maxLenth = paramLine4List.size();
        }
        if (paramLine5List.size() > maxLenth) {
            maxLenth = paramLine5List.size();
        }
        if (paramLine6List.size() > maxLenth) {
            maxLenth = paramLine6List.size();
        }

        while (paramLine1List.size() < maxLenth) {
            paramLine1List.add("0");
        }
        while (paramLine2List.size() < maxLenth) {
            paramLine2List.add("0");
        }
        while (paramLine3List.size() < maxLenth) {
            paramLine3List.add("0");
        }
        while (paramLine4List.size() < maxLenth) {
            paramLine4List.add("0");
        }
        while (paramLine5List.size() < maxLenth) {
            paramLine5List.add("0");
        }
        while (paramLine6List.size() < maxLenth) {
            paramLine6List.add("0");
        }

        File dirFile = new File(dirPath);
        try {
            FileUtil.forceMkdir(dirFile);

            File paramFile = new File(dirFile, taskId + "_Para.txt");
            FileUtil.write(paramFile, "");//有文件的话清空文件

            for (int i = 0; i < paramLine1List.size(); i++) {
                if (i == paramLine1List.size() - 1) {
                    FileUtil.write(paramFile, paramLine1List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine1List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine2List.size(); i++) {
                if (i == paramLine2List.size() - 1) {
                    FileUtil.write(paramFile, paramLine2List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine2List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine3List.size(); i++) {
                if (i == paramLine3List.size() - 1) {
                    FileUtil.write(paramFile, paramLine3List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine3List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine4List.size(); i++) {
                if (i == paramLine4List.size() - 1) {
                    FileUtil.write(paramFile, paramLine4List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine4List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine5List.size(); i++) {
                if (i == paramLine5List.size() - 1) {
                    FileUtil.write(paramFile, paramLine5List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine5List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine6List.size(); i++) {
                if (i == paramLine6List.size() - 1) {
                    FileUtil.write(paramFile, paramLine6List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine6List.get(i) + "\t", true);
                }
            }
        } catch (IOException e) {
            LogUtil.errorLog(e, "");
        }
        return true;
    }

    /**
     245	100	0	0
     0	0	0	0
     1	1	1	1
     1	1	2	3
     0.50	0.30	0.20	0
     0.50	0.30	0.20	0
     0.05	0.10	0.02	0.004
     0.5	0.8	0.4	0.1
     输入参数解释：与之前的输入一样，这次的*_Para.txt是一个矩阵，并且是一个列数相同的矩阵。
     Para(1,1) 表示求历史指数回溯期间的窗口大小（1年就是245，3年就是3*245）。
     Para(1,2) 表示所求解的有效前沿的点数。
     Para(2-3,:)第二行和第三行跟马尔科维茨有效前沿一样，表示资产的下线和上限。
     Para(4,:) 第四行跟马尔科维茨有效前沿一样，表示资产类别的分组号。
     Para(5-6,:)第五行和第六行跟马尔科维茨有效前沿一样，表示资产分组的上下限 。
     Para(7,:) 第七行是新增的，表示对各类资产年化收益的主观判断 。（列数应该与输入资产的数量相等）
     Para(8,:) 第八行是新增的，表示对各类资产年化收益的可信度。（列数应该与输入资产的数量相等）
     * @param dirPath
     * @param taskId
     * @param combinatorialTaskParams
     * @param assetStrategyMap
     * @return
     */
    public boolean genBlackLittermanParaFile(String dirPath, String taskId, TaskParams combinatorialTaskParams,Map<Integer,Double> assetStrategyMap) {
        List<String> paramLine1List = new ArrayList<String>();
        List<String> paramLine2List = new ArrayList<String>();
        List<String> paramLine3List = new ArrayList<String>();
        List<String> paramLine4List = new ArrayList<String>();
        List<String> paramLine5List = new ArrayList<String>();
        List<String> paramLine6List = new ArrayList<String>();
        List<String> paramLine7List = new ArrayList<String>();
        List<String> paramLine8List = new ArrayList<String>();

        List<TaskParams.ModelParamsBean> combinatorialModelParams = combinatorialTaskParams.getModelParams();


        List<UpDownParamsBean> combinatorialUpDownParamsBeanList = combinatorialTaskParams.getUpDownParams();


        int combinatorialAssetStrategyLen = combinatorialUpDownParamsBeanList.size();

        String combinatorialTraceLengthParam = combinatorialModelParams.get(0).getValue();

        int traceLength = 3 * 245, dotCountOnchart = 100;

        if ("1".equals(combinatorialTraceLengthParam)) {
            traceLength = 1 * 245;
        } else if ("2".equals(combinatorialTraceLengthParam)) {
            traceLength = 3 * 245;
        } else if ("3".equals(combinatorialTraceLengthParam)) {
            traceLength = 5 * 245;
        }

        paramLine1List.add(traceLength + "");
        paramLine1List.add(dotCountOnchart + "");


        for (int i = 0; i < combinatorialUpDownParamsBeanList.size(); i++) {
            UpDownParamsBean upDownParamsBean = combinatorialUpDownParamsBeanList.get(i);
            paramLine2List.add(Long.valueOf(upDownParamsBean.getDown()) / 100D + "");
            paramLine3List.add(Long.valueOf(upDownParamsBean.getUp()) / 100D + "");
            paramLine4List.add(upDownParamsBean.getAssetStrategyId() + "");
            if(null == assetStrategyMap){
                paramLine5List.add(Long.valueOf(upDownParamsBean.getDown()) / 100D + "");
                paramLine6List.add(Long.valueOf(upDownParamsBean.getUp()) / 100D + "");
            }else {
                paramLine5List.add(assetStrategyMap.get(upDownParamsBean.getAssetStrategyId()) + "");
                paramLine6List.add(assetStrategyMap.get(upDownParamsBean.getAssetStrategyId()) + "");
            }

        }

        List<TaskParams.ViewPointParamsBean> viewPointParams = combinatorialTaskParams.getViewpointParams();

        for(int i=0;i<viewPointParams.size();i++){
            TaskParams.ViewPointParamsBean viewPointParamsBean = viewPointParams.get(i);
            paramLine7List.add(viewPointParamsBean.getViewpoint().toString());
            paramLine8List.add(viewPointParamsBean.getConfidence().toString());
        }

        int maxLenth = paramLine1List.size();
        if (paramLine2List.size() > maxLenth) {
            maxLenth = paramLine2List.size();
        }
        if (paramLine3List.size() > maxLenth) {
            maxLenth = paramLine3List.size();
        }
        if (paramLine4List.size() > maxLenth) {
            maxLenth = paramLine4List.size();
        }
        if (paramLine5List.size() > maxLenth) {
            maxLenth = paramLine5List.size();
        }
        if (paramLine6List.size() > maxLenth) {
            maxLenth = paramLine6List.size();
        }
        if (paramLine7List.size() > maxLenth) {
            maxLenth = paramLine7List.size();
        }
        if (paramLine8List.size() > maxLenth) {
            maxLenth = paramLine8List.size();
        }

        while (paramLine1List.size() < maxLenth) {
            paramLine1List.add("0");
        }
        while (paramLine2List.size() < maxLenth) {
            paramLine2List.add("0");
        }
        while (paramLine3List.size() < maxLenth) {
            paramLine3List.add("0");
        }
        while (paramLine4List.size() < maxLenth) {
            paramLine4List.add("0");
        }
        while (paramLine5List.size() < maxLenth) {
            paramLine5List.add("0");
        }
        while (paramLine6List.size() < maxLenth) {
            paramLine6List.add("0");
        }
        while (paramLine7List.size() < maxLenth) {
            paramLine7List.add("0");
        }
        while (paramLine8List.size() < maxLenth) {
            paramLine8List.add("0");
        }

        File dirFile = new File(dirPath);
        try {
            FileUtil.forceMkdir(dirFile);

            File paramFile = new File(dirFile, taskId + "_Para.txt");
            FileUtil.write(paramFile, "");//有文件的话清空文件

            for (int i = 0; i < paramLine1List.size(); i++) {
                if (i == paramLine1List.size() - 1) {
                    FileUtil.write(paramFile, paramLine1List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine1List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine2List.size(); i++) {
                if (i == paramLine2List.size() - 1) {
                    FileUtil.write(paramFile, paramLine2List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine2List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine3List.size(); i++) {
                if (i == paramLine3List.size() - 1) {
                    FileUtil.write(paramFile, paramLine3List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine3List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine4List.size(); i++) {
                if (i == paramLine4List.size() - 1) {
                    FileUtil.write(paramFile, paramLine4List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine4List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine5List.size(); i++) {
                if (i == paramLine5List.size() - 1) {
                    FileUtil.write(paramFile, paramLine5List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine5List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine6List.size(); i++) {
                if (i == paramLine6List.size() - 1) {
                    FileUtil.write(paramFile, paramLine6List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine6List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine7List.size(); i++) {
                if (i == paramLine7List.size() - 1) {
                    FileUtil.write(paramFile, paramLine7List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine7List.get(i) + "\t", true);
                }
            }
            for (int i = 0; i < paramLine8List.size(); i++) {
                if (i == paramLine8List.size() - 1) {
                    FileUtil.write(paramFile, paramLine8List.get(i) + "\n", true);
                } else {
                    FileUtil.write(paramFile, paramLine8List.get(i) + "\t", true);
                }
            }
        } catch (IOException e) {
            LogUtil.errorLog(e, "");
        }
        return true;
    }

    public boolean write2ParamFile(File paramFile, List<String>... lists) {
        int maxLenth = 0;
        for (List<String> list : lists) {
            if (list.size() > maxLenth) {
                maxLenth = list.size();
            }
        }

        for (List<String> list : lists) {
            while (list.size() < maxLenth) {
                list.add("0");
            }
        }

        try {
            FileUtil.write(paramFile, "");//有文件的话清空文件

            for (List<String> list : lists) {
                for (int i = 0; i < list.size(); i++) {
                    if (i == list.size() - 1) {
                        FileUtil.write(paramFile, list.get(i) + "\n", true);
                    } else {
                        FileUtil.write(paramFile, list.get(i) + "\t", true);
                    }
                }
            }
        } catch (IOException e) {
            LogUtil.errorLog(e, "");
            return false;
        }
        return true;
    }

    /**
     * 根据taskId获取相关性矩阵
     *
     * @param taskId
     * @return
     */
    public List<String> getCovResult(String taskId) {
        FofTask fofTask = this.getTaskByTaskId(taskId);
        if (null == fofTask || StringUtil.isBlank(fofTask.getDataDir())) {
            return null;
        }
        File dirFile = new File(fofTask.getDataDir());
        List<String> covResultList = null;
        try {
            File paramFile = new File(dirFile, taskId + "_COV.txt");
            List<String> allLines = FileUtil.readLines(paramFile);
            covResultList = new ArrayList<String>();
            for (String line : allLines) {
                covResultList.addAll(Arrays.asList(line.split("\t")));
            }
        } catch (Exception e) {
            LogUtil.errorLog(e, "getCovResult error");
        }
        return covResultList;
    }

    /**
     * 更新资产/策略配置这一步用户选的资产比例到fofTask表
     * @param bizId
     * @param assetStrategyResult
     * @return
     */
    public boolean setFofTaskAssetStrategyResult(String bizId,String assetStrategyResult){
        FofTask fofTask = this.getTaskByBizIdAndType(bizId,1);
        if(null != fofTask){
            fofTask.setAssetStrategyResult(assetStrategyResult);
            int ret = this.updateIgnoreNull(fofTask);
            if(ret == 1){
                return true;
            }else{
                return false;
            }
        }
        return false;
    }

    private Map<Integer,Double> parseAssetStrategyResult(String assetStrategyResultStr){
        try{
            JSONArray jsonArray = JsonUtil.pase2JsonArray(assetStrategyResultStr);
            if(null == jsonArray || jsonArray.size() == 0){
                return Collections.emptyMap();
            }
            Map<Integer,Double> assetStrategyMap = new HashMap<Integer, Double>();
            for(int i=0;i<jsonArray.size();i++){
                JSONObject itemObject = jsonArray.getJSONObject(i);

                AssetStrategyInfo assetStrategyInfo = assetStrategyInfoService.getAssetStrategyInfoByName(itemObject.getString("name"));
                int assetStrategyId = 0;
                if(null != assetStrategyInfo){
                    assetStrategyId = assetStrategyInfo.getId();
                }
                assetStrategyMap.put(assetStrategyId,itemObject.getDouble("val"));
            }
            return assetStrategyMap;

        }catch (Exception e){
            LogUtil.errorLog(e,"parseAssetStrategyResult error");
        }
        return Collections.emptyMap();

    }
}
